home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / std_unix / archive / text0071.txt < prev    next >
Encoding:
Text File  |  1993-07-06  |  19.6 KB  |  644 lines

  1. Submitted-by: jsh@teal.csn.org (Jeffrey Haemer)
  2.  
  3. Folks,
  4.  
  5. A few weeks back, we posted a note asking for your advice and aid
  6. in prototyping software for electronic standards balloting.  We
  7. got it.  Thanks.  Now we want some more.
  8.  
  9. Here's a shar with a first cut at some balloting software.  Unshar
  10. it, read the README, and the rest should be self-explanatory.
  11. We're looking for advice, bugs, bug-fixes, enhancements, and users.
  12. The shar includes our original post, explaining our goal in more detail.
  13.  
  14. Jeffrey S. Haemer, USENIX Standards Liaiason    <jsh@usenix.org>
  15. Pat Wilson, SAGE Board Member            <paw@rigel.dartmouth.edu>
  16.  
  17. ========
  18. #! /bin/sh
  19. # This is a shell archive.  Remove anything before this line, then unpack
  20. # it by saving it into a file and typing "sh file".  To overwrite existing
  21. # files, type "sh file -c".  You can also feed this as standard input via
  22. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  23. # will see the following message at the end:
  24. #        "End of archive 1 (of 1)."
  25. # Contents:  Environ.pl Mail.pl README ballot balloting.mm vote
  26. # Wrapped by ballot@canary.com on Fri Jun  4 14:11:16 1993
  27. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  28. if test -f 'Environ.pl' -a "${1}" != "-c" ; then 
  29.   echo shar: Will not clobber existing file \"'Environ.pl'\"
  30. else
  31. echo shar: Extracting \"'Environ.pl'\" \(1773 characters\)
  32. sed "s/^X//" >'Environ.pl' <<'END_OF_FILE'
  33. X# $Id: Environ.pl,v 3.0 1993/06/04 19:53:34 ballot Exp ballot $
  34. X
  35. Xpackage Environ;
  36. X# print the environment
  37. Xsub 'printenv {
  38. X    foreach (sort keys %ENV) {
  39. X        print "$_=$ENV{$_}\n";
  40. X    }
  41. X}
  42. X
  43. X# set environment variables
  44. X#    override and add to the values in ENV
  45. X#    with values specified in a resource file.
  46. X#    The resource file is specified by RESOURCE
  47. Xsub 'setenv {
  48. X    local(@path) = split(m%/%, $0);
  49. X    local($cmd) = pop(@path);
  50. X    %ENV = &'get_arr($cmd, %ENV) unless ($'setenv'guard++)
  51. X}
  52. X
  53. X# fill an array from a specified file
  54. X#    Use the first argument as the name of an environment variable
  55. X#    that points at the keyfile.
  56. X#    If that fails, try a file by the name of arg1
  57. X#    Use the second argument as an array of default values
  58. X#
  59. X#    See setenv() as an example.
  60. X#
  61. X#    BUGS:
  62. X#        I don't get why I can't combine the lines marked with "?".
  63. X#
  64. Xsub 'get_arr {
  65. X    local($keyfile) = shift(@_);
  66. X    local (%arr) = @_;
  67. X    open(KEYS,  $ENV{$keyfile} = $ENV{$keyfile} ?  $ENV{$keyfile} : ("$keyfile.res") ) || return %arr;
  68. X    while (<KEYS>) {
  69. X        chop;
  70. X        ($name, $other) = split(' ', $_, 2);    # ?
  71. X        $arr{$name} = $other;            # ?
  72. X    }
  73. X    close(KEYS) || die "can't close $keyfile: $!, aborting\n";
  74. X    return %arr;
  75. X}
  76. X
  77. X# Test routine.  Invoke it in a driver with 
  78. X#    require "Environ.pl";
  79. X#    &Environ'test;
  80. Xsub test {
  81. X    &'setenv;
  82. X    %arr = &'get_arr("foo", %ENV);
  83. X    die "get_arr failed to get ENV\n" unless $arr{HOME} = $ENV{HOME};
  84. X    $arr{HOME} = NULL;
  85. X
  86. X    open(IN, "foo.res");
  87. X    print IN "HOME\tBOGUS\n";
  88. X    close(IN);
  89. X    %arr = &'get_arr("foo", %ENV);
  90. X    die "getarr failed to read foo.res\n" unless $arr{HOME} = "BOGUS";
  91. X    $arr{HOME} = NULL;
  92. X
  93. X    $ENV{"bar"} = "foo.res";
  94. X    %arr = &'get_arr("bar", %ENV);
  95. X    die "getarr failed to read ENV{bar}\n" unless $arr{HOME} = "BOGUS";
  96. X    $arr{HOME} = NULL;
  97. X
  98. X    unlink("foo.res");
  99. X    print "Package tests okay.\n";
  100. X}
  101. X
  102. X1;
  103. END_OF_FILE
  104. if test 1773 -ne `wc -c <'Environ.pl'`; then
  105.     echo shar: \"'Environ.pl'\" unpacked with wrong size!
  106. fi
  107. chmod +x 'Environ.pl'
  108. # end of 'Environ.pl'
  109. fi
  110. if test -f 'Mail.pl' -a "${1}" != "-c" ; then 
  111.   echo shar: Will not clobber existing file \"'Mail.pl'\"
  112. else
  113. echo shar: Extracting \"'Mail.pl'\" \(2375 characters\)
  114. sed "s/^X//" >'Mail.pl' <<'END_OF_FILE'
  115. X# $Id: Mail.pl,v 3.0 1993/06/04 19:53:34 ballot Exp ballot $
  116. X
  117. Xrequire "Environ.pl";
  118. X
  119. Xpackage Mail;
  120. X
  121. X@MAILER = ("/usr/bin/mailx", "/bin/mail", "/usr/bin/mail", "/usr/ucb/Mail");
  122. X
  123. X# get key lines
  124. X#    Return each key value
  125. X#    in the current item in an associative array.
  126. X#    keylines are specified by regular expressions
  127. X#    in a file named by the second argument,
  128. X#    default expressions are supplied in the third.
  129. Xsub 'getkeys {
  130. X
  131. X    local($_, $keyfile, %defaults) = @_;
  132. X    
  133. X    %keyline = &'get_arr($keyfile, %defaults) unless ($getkeys'guard++);
  134. X    local(%info);
  135. X    local($*) = 1;
  136. X    for $k (keys %keyline) {
  137. X        $info{$k} = $1 if (/$keyline{$k}/);
  138. X    }
  139. X    return %info;
  140. X}
  141. X
  142. X# get all the mail messages
  143. X#    Toss the entire mail file into an array, one element per message.
  144. X#    Return the array
  145. Xsub 'getmsgs {
  146. X    open(INBOX, $_[0])        || die "can't open $_[0]: $!, aborting\n";
  147. X    local($/) = '';
  148. X    @msg = ();
  149. X    $msg = '';
  150. X    while(<INBOX>) {
  151. X        if (/^From /) {
  152. X            push(@msg, $msg) if $msg;
  153. X            $msg = '';
  154. X        }
  155. X        $msg .= $_;
  156. X    }
  157. X    push (@msg, $msg) if $msg;
  158. X    return @msg;
  159. X}
  160. X
  161. X# mail a message
  162. X#    just a call to the native mail program
  163. X#
  164. X#    BUGS: I worry a bit about the diversity of mail programs
  165. Xsub 'mailx {
  166. X    die "bad call to mailx\n" unless @_ > 2;    # try assert
  167. X    local($sub, $to, @msg) = @_;
  168. X    ($ENV{MAILER}) = grep(-x, @MAILER) unless $ENV{MAILER};
  169. X    $cmd = "| $ENV{MAILER} -s '$sub' $to";
  170. X    open(ACKMAIL, $cmd)            || die "can't open $cmd: $!, aborting\n";
  171. X    print ACKMAIL @msg;
  172. X    close(ACKMAIL)                || die "can't close $cmd: $!, aborting\n";
  173. X}
  174. X
  175. X# Test routine.  Invoke it in a driver with 
  176. X#    require "Mail.pl";
  177. X#    &Mail'test;
  178. X
  179. X# default values.  %KEYLINES is probably the wrong set
  180. X@MAILDIR = ("/var/spool/mail", "/var/mail", "/usr/spool/mail");
  181. X%KEYLINE =    (
  182. X        'Checksum',    'Checksum:\s*(\d+\s*\d+)',
  183. X        'From',        '^From:\s*(.*)',
  184. X        'Author',    'Author:\s*(.*)',
  185. X        'ID',        'ID:\s*(\d+)',
  186. X        'Subject',    '^Subject:\s*(.*)',
  187. X        'Vote',        'Vote:\s*(.+)',
  188. X        );
  189. X
  190. Xsub test {
  191. X    setpwent;
  192. X    ($name) = getpwuid($>);        # I dunno, why not?
  193. X    endpwent;
  194. X    &'mailx("Zzazz", $name, "This is the first line\nThis is the second\n");
  195. X    sleep 10;
  196. X    ($maildir) = grep(-e, @MAILDIR);
  197. X    @msgs = &'getmsgs("$maildir/$name");
  198. X    $newmsg = pop(@msgs);
  199. X    %info = &'getkeys($newmsg, "keyline", %KEYLINE);
  200. X
  201. X    die "Bad subject line $info{Subject}\n" if "Zzazz" != $info{Subject};
  202. X    die "Bad recipient line $info{To}\n" if "Zzazz" != $info{To};
  203. X    print "Package tests okay.\n";
  204. X}
  205. X
  206. X1;
  207. END_OF_FILE
  208. if test 2375 -ne `wc -c <'Mail.pl'`; then
  209.     echo shar: \"'Mail.pl'\" unpacked with wrong size!
  210. fi
  211. # end of 'Mail.pl'
  212. fi
  213. if test -f 'README' -a "${1}" != "-c" ; then 
  214.   echo shar: Will not clobber existing file \"'README'\"
  215. else
  216. echo shar: Extracting \"'README'\" \(4209 characters\)
  217. sed "s/^X//" >'README' <<'END_OF_FILE'
  218. X# $Id: README,v 3.0 1993/06/04 19:53:34 ballot Exp ballot $
  219. X
  220. XThis is a cut at balloting software.
  221. X
  222. X
  223. X            INSTALLATION
  224. X
  225. XThe system receiving the votes should have a special id to process
  226. Xthe votes, and votes should be sent to that id (e.g.
  227. X<posix-dot-fifty@canary.com>).
  228. X
  229. XYou _must_ create an initial, two-column file of valid voters,
  230. X"ids.res".  Each voter needs an id, and must know that id to vote.
  231. X(The format of the file is "ID  Votername".) For IEEE standards
  232. Xballots, for example, you might want to make the list be a list of
  233. XIEEE members and their IEEE membership numbers.
  234. X
  235. XThe system has reasonable defaults, but it's fairly configurable;
  236. Xit lets you use external files to specify what kinds of votes can
  237. Xbe cast, where the mailboxes are, and all sorts of other things.
  238. XUnfortunately, you currently have to read the code to understand
  239. Xhow to configure it.
  240. X
  241. XCurrently, the scripts point at /usr/bin/perl.  If your system has
  242. Xperl someplace else, you'll get non-informative error messages.
  243. X
  244. X
  245. X            WHAT IT DOES
  246. X
  247. XVoters run "vote" to cast ballots.  The recipient of the votes runs
  248. X"ballot" to count ballots.
  249. X
  250. X"vote" insures that the ballot has all the right fields,
  251. Xthen tags a checksum on the end.
  252. X
  253. X"ballot" runs through the incoming mailbox and sorts the votes into
  254. Xbins.  In doing so, it validates the balloter and the checksum,
  255. Xand sends the sender an acknowledgment of the receipt of the vote.
  256. X
  257. X
  258. X        WHAT IT DOESN'T DO: KNOWN PROBLEMS/PROJECTS
  259. X
  260. XThere should be a good configuration and installation script.
  261. X
  262. XCurrently, the scripts point at /usr/bin/perl.  If your system has
  263. Xperl someplace else, you'll get non-informative error messages.
  264. XThis could probably be fixed with a good configuration and
  265. Xinstallation script.
  266. X
  267. XOther software that needs to be written are a utility for tallying
  268. Xvotes and a utility for processing invalid votes.  We have contributed
  269. Xsoftware that parses valid votes once they're binned, but it's not yet
  270. Xready to post.
  271. X
  272. XThe "ids.res" file (and its processing) could be more sophisticated.
  273. XIn particular, if it contained an email address, we could have a
  274. Xdaemon periodically run through the file and send mail noodging
  275. Xthose who haven't yet voted.
  276. X
  277. XKnown problems awaiting future solution are indicated in comments
  278. Xthe code.  Those problems should probably be listed here instead,
  279. Xor at least duplicated here.
  280. X
  281. XCurrently, the first vote from a voter that shows up in the mailbox
  282. Xis the one that counts.  This has two shortcomings.  First, if
  283. Xthe messages arrive out-of-order, this isn't the right choice.
  284. XSecond, we might want to allow people to change their minds, in
  285. Xwhich case we should probably use the _last_ message that arrives.
  286. XPerhaps this should be a configuration or command-line option.
  287. X
  288. XThere should be a man page that doesn't make you read the code to
  289. Xfigure out how to configure things.
  290. X
  291. X"ballot" doesn't make any effort to lock the input mailbox.  That's
  292. Xbecause I don't really know how to do this.  It also doesn't do
  293. Xvery fancy security, for the same reason.  (Currently, "vote" appends
  294. Xa simple checksum to the message which is double-checked by "ballot",
  295. Xand then returned to the sender so that the sender can be certain that
  296. Xthe checksum received was the one sent.)
  297. X
  298. XBecause different groups may want different security levels or
  299. Xalgorithms, perhaps the security/checksumming should be done by a
  300. Xseparate executable that "vote" and "ballot" call as a subprocess.
  301. X
  302. X
  303. X            PHILOSOPHICAL OBSERVATION
  304. X
  305. XIt is arguably ironic that this balloting software, initially
  306. Xdesigned to help ballot standards documents, is in a non-standardized
  307. Xlanguage.  I suspect that the fastest way to whip this suite into
  308. Xshape is to ask that everyone who chooses to comment on this amusing
  309. Xirony accompany the comment with an improvement to the software.
  310. X(Figure, it's either that or we create a group to standardize perl ... :-)
  311. X
  312. X
  313. X                FILES
  314. X
  315. XEnvPkg.pl    A package to get and set environment variables and resources
  316. XMailPkg.pl    A package that handles the mail messages
  317. XREADME        This file
  318. Xballot        Sorts mail file into bins of each kind of vote
  319. Xids.res        A two-column list of folks yet to vote: ID Name
  320. Xvote        script to generate a vote
  321. Xvoted.res    Folks who have already voted, same format as "ids"
  322. END_OF_FILE
  323. if test 4209 -ne `wc -c <'README'`; then
  324.     echo shar: \"'README'\" unpacked with wrong size!
  325. fi
  326. # end of 'README'
  327. fi
  328. if test -f 'ballot' -a "${1}" != "-c" ; then 
  329.   echo shar: Will not clobber existing file \"'ballot'\"
  330. else
  331. echo shar: Extracting \"'ballot'\" \(4819 characters\)
  332. sed "s/^X//" >'ballot' <<'END_OF_FILE'
  333. X#!/usr/bin/perl
  334. X# $Id: ballot,v 3.0 1993/06/04 19:53:34 ballot Exp ballot $
  335. X
  336. Xrequire "Mail.pl";
  337. X
  338. X@MAILDIRS = ("/var/spool/mail", "/var/mail", "/usr/spool/mail");
  339. X%CHOICES  = (
  340. X    YES, "yes",
  341. X    NO, "no",
  342. X    ABSTAIN, "abstain",
  343. X);
  344. X
  345. X%KEYLINE =    (
  346. X        'Checksum',    'Checksum:\s*(\d+\s*\d+)',
  347. X        'From',        '^From:\s*(.*)',
  348. X        'Author',    'Author:\s*(.*)',
  349. X        'ID',        'ID:\s*(\d+)',
  350. X        'Subject',    '^Subject:\s*(.*)',
  351. X        'Vote',        'Vote:\s*(.+)',
  352. X        );
  353. X
  354. X# acknowledge a message
  355. X#    parse out the sender,
  356. X#    return an ack with enough information to let the recipient know
  357. X#    what we actually got.
  358. Xsub ack {
  359. X    local($sub) = "Vote received";
  360. X    local($to) = $Keyline{From};
  361. X    local(@ack) =    (
  362. X            "Received vote:    $Keyline{Vote}\n",
  363. X            "Voter:        $Keyline{Author}\n",
  364. X             "ID:        $Keyline{ID}\n",
  365. X            "Checksum:    $Keyline{Checksum}\n",
  366. X            "Msg subject:    $Keyline{Subject}\n"
  367. X            );
  368. X
  369. X    # optional "To" line formats
  370. X    if ($to =~ /<(\S*)>/) {
  371. X        $to = $1;
  372. X    } elsif ($to =~ /(\S*)\s*\(.*\)/) {
  373. X        $to = $1;
  374. X    } else {
  375. X        return 0;
  376. X    }
  377. X    &mailx($sub, $to, @ack);
  378. X    1;
  379. X}
  380. X
  381. X# 'bin' an individual message
  382. X#    Make sure the vote's legit and acknowledge it,
  383. X#    then toss the message into the bin
  384. X#    indicated in the message's "Vote:" field.
  385. Xsub bin {
  386. X    local($msg) = @_[0];
  387. X    %Keyline = &'getkeys($msg, "keyline", %KEYLINE);
  388. X    local($vote) = $Keyline{Vote};
  389. X    foreach (keys %Choices) {
  390. X        $vote = $_, last if $vote =~ /$Choices{$_}/i
  391. X    }
  392. X    $vote = BAD unless (&valid($msg) && $vote && &ack());
  393. X    $tally{$vote}++;
  394. X    print $vote $msg;
  395. X}
  396. X
  397. X# check out the checksum
  398. X#    Right now, expects messages to end with the two lines
  399. X#        Checksum: nnnn nnnn
  400. X#
  401. X#    where the numbers come from running cksum
  402. X#    on the rest of the message body
  403. X#
  404. X#    BUGS: Okay, okay, this isn't any good.
  405. X#    Still, little point wasting time here
  406. X#    until I know what the right thing to do is.
  407. Xsub cksum {
  408. X    local($msg) = @_[0];
  409. X    return 1;
  410. X    # $*=1;
  411. X    @text = split(/\n\n/, $msg);            # split out the header
  412. X    shift(@text);                    # and dump it
  413. X    @text = split(/^Checksum: /, join(' ', @text));    # now the get the checksum
  414. X    $checksum = pop(@text);
  415. X    $checksum = unpack("%32C*", join(' ', @text));
  416. X}
  417. X
  418. X# clean up
  419. X#    print out the tally;
  420. X#    rewrite the "ids" (yet-to-vote) and "voted" files;
  421. X#    finally close open files
  422. X#    removing any that got created but never used
  423. Xsub clean_up {
  424. X    &tally(%tally);
  425. X    open(IDS, "> $ENV{'ids'}")        || die "can't open $ENV{ids} for write: $!, aborting\n";
  426. X    open(VOTED, ">> $ENV{'voted'}")        || die "can't open $ENV{voted} for append: $!, aborting\n";
  427. X    foreach (keys %Ids) {
  428. X        print { $Voted{$_} ? VOTED : IDS } "$_\t$Ids{$_}\n";
  429. X    }
  430. X    close(IDS)            || die "can't close $ENV{ids}: $!, aborting\n";
  431. X    close(VOTED)            || die "can't close $ENV{voted}: $!, aborting\n";
  432. X    close(BAD)            || die "can't close BAD: $!, aborting";
  433. X    foreach (BAD, $ENV{"ids"}, $ENV{"voted"}) {
  434. X        unlink $_ if -z $_;
  435. X    }
  436. X
  437. X    unlink("BAD") if -z "BAD";
  438. X    foreach (keys %Choices) {
  439. X        close($_)        || die "can't close $_: $!, aborting";
  440. X        unlink $_ if -z $_;
  441. X    }
  442. X}
  443. X
  444. X# all the initialization
  445. X#    open up the input mailbox and the output mailboxes.
  446. X#    note that votes are cumulative
  447. X#
  448. X#    BUGS: needs to lock the input mailbox,
  449. X#    then move it out of the way so ballots aren't counted twice
  450. Xsub initialize {
  451. X    &setenv;
  452. X    die "No valid voters\n" unless %Ids = &get_arr("ids");
  453. X    local(%voted) = &get_arr("voted");
  454. X     foreach (keys %voted) {
  455. X         $Voted{$_}++;
  456. X    }
  457. X
  458. X    ($Maildir) = grep(-e, @MAILDIRS);
  459. X    ($Name) = getpwuid($>);        # I dunno, why not?
  460. X    $ENV{BALLOT_BOX} = $ENV{BALLOT_BOX} || "$Maildir/$Name";
  461. X    $ENV{"voted"} = $ENV{"voted"} || "voted.res";
  462. X    die "No votes\n" if ( -z $ENV{BALLOT_BOX} || ! -e $ENV{BALLOT_BOX} );
  463. X    %Choices = &get_arr("choices", %CHOICES);
  464. X    foreach (keys %Choices) {
  465. X        open($_, ">> $_")        || die "can't open $_ for append: $!, aborting\n";
  466. X    }
  467. X    open(BAD, ">> BAD")            || die "can't open BAD for append: $!, aborting\n";
  468. X}
  469. X
  470. X# tally the votes
  471. X#    just print out the tallies from this batch of mail
  472. X#
  473. X#    BUGS: This is just a debugging tool.
  474. X#    Tallying should be done by a separate process
  475. X#    and go directly to the tally bins.
  476. Xsub tally {
  477. X    local(%tally) = @_;
  478. X    foreach (sort keys %tally) {
  479. X        print "$_=$tally{$_}\n";
  480. X    }
  481. X}
  482. X
  483. X# validate the message
  484. X#    Read the file that matches IDs to voter names,
  485. X#    then check that the message "ID:" field has the right "Name:" field.
  486. X#    and that the checksum matches the message.
  487. X#    Don't allow ballot-box stuffing -- only vote once.
  488. X#
  489. X#    BUGS: May need other checks.
  490. X#
  491. X#    Assumes access to a global %Keyline array,
  492. X#    which is probably the wrong thing to do.
  493. X#    This should all be modularized and stuff.
  494. Xsub valid {
  495. X    local($msg) = @_[0];
  496. X    ++$Voted{$Keyline{ID}} if
  497. X        ($Keyline{Author} eq $Ids{$Keyline{ID}})
  498. X        && &cksum($msg)
  499. X        && !$Voted{$Keyline{ID}};
  500. X}
  501. X
  502. X# read mail messages from mailbox
  503. X# and toss them one-by-one into an appropriate output mailbox
  504. X
  505. X&initialize;
  506. X@msg = &getmsgs($ENV{BALLOT_BOX});
  507. Xwhile($msg = shift(@msg)) {
  508. X    &bin($msg);
  509. X}
  510. X&clean_up;
  511. END_OF_FILE
  512. if test 4819 -ne `wc -c <'ballot'`; then
  513.     echo shar: \"'ballot'\" unpacked with wrong size!
  514. fi
  515. chmod +x 'ballot'
  516. # end of 'ballot'
  517. fi
  518. if test -f 'balloting.mm' -a "${1}" != "-c" ; then 
  519.   echo shar: Will not clobber existing file \"'balloting.mm'\"
  520. else
  521. echo shar: Extracting \"'balloting.mm'\" \(1852 characters\)
  522. sed "s/^X//" >'balloting.mm' <<'END_OF_FILE'
  523. X.\" $Id: balloting.mm,v 1.1 1993/06/04 20:10:15 ballot Exp ballot $
  524. X.\" Uses the mm macro ".PH", but that's all
  525. X.PH "''''"
  526. X.ce
  527. XElectronic Balloting Software
  528. X
  529. XWhat if you could FTP POSIX draft standards and ballot on them from
  530. Xthe comfort of your own keyboard?  No more messy stamps or ink-stained
  531. Xfingers!  No need to wait on the Postal "Service" for the latest
  532. Xdrafts!
  533. X
  534. XWe see a future in which draft standards will be available for
  535. Xanonymous FTP, and balloting can be done by email.  For a variety
  536. Xof reasons -- some sensible, some merely historical -- achieving
  537. Xeither of these advances requires overcoming both political and
  538. Xtechnical barriers.  We'd like to remove the technical barriers.
  539. XAndrew Hume has already demonstrated a prototype solution for
  540. Xelectronic draft distribution.  We'd like to see a prototype for
  541. Xelectronic balloting, and we'd like your help to make this happen.
  542. X
  543. XIt's envisioned that any electronic balloting procedure will need
  544. X(a) authentication at least as good as Snail Mail provides and (b)
  545. Xvote-counting software to make it as painless as possible.
  546. X
  547. XQuick-and-dirty authentication can be as simple as (1) mail the
  548. Xballot-request software, which then (2) generates an encryption
  549. Xkey and (3) sends it, via postal mail (wouldn't want them to feel
  550. X_too_ left out!) to the requester, who then (4) uses the out-of-band
  551. Xkey to encrypt the ballot, which is then (5) decrypted by the
  552. Xballoting software and (6) counted appropriately -- or at least
  553. Xthat's the plan.
  554. X
  555. XWhat's wrong with the plan?  How can it be made better?  How
  556. Xinteresting can the vote-counting software get?  Should it be
  557. Xwritten in perl?
  558. X
  559. XPlease contribute your thoughts, code, etc., and help POSIX balloting
  560. Xstep into the 1990s.
  561. X
  562. X
  563. X.nf
  564. X- Jeffrey S. Haemer, USENIX Standards Liaison    <jsh@usenix.org>
  565. X- Pat Wilson, SAGE Board Member    <paw@rigel.dartmouth.edu>
  566. X.fi
  567. END_OF_FILE
  568. if test 1852 -ne `wc -c <'balloting.mm'`; then
  569.     echo shar: \"'balloting.mm'\" unpacked with wrong size!
  570. fi
  571. # end of 'balloting.mm'
  572. fi
  573. if test -f 'vote' -a "${1}" != "-c" ; then 
  574.   echo shar: Will not clobber existing file \"'vote'\"
  575. else
  576. echo shar: Extracting \"'vote'\" \(836 characters\)
  577. sed "s/^X//" >'vote' <<'END_OF_FILE'
  578. X#!/usr/bin/perl
  579. X# $Id: vote,v 3.0 1993/06/04 19:53:34 ballot Exp ballot $
  580. X
  581. X# send in a ballot
  582. X#    Tags a checksum on the end.
  583. X#
  584. X#    BUGS:
  585. X#        The program should probably save the checksum,
  586. X#        or even the completed ballot, somewhere
  587. X#        so the user can verify that the acknowledgement
  588. X#        matches what was sent.
  589. X#        Right now, I use mail's "set record=" feature for this.
  590. X
  591. Xrequire "Mail.pl";
  592. X
  593. X@KEYWORDS = (Author, ID, Vote);
  594. X
  595. Xdie "Usage $0 ballot address\n" if (@ARGV != 2);
  596. Xopen(BALLOT, $ARGV[0]);
  597. Xwhile (<BALLOT>) {
  598. X    push (@msg, $_);
  599. X    foreach $k (@KEYWORDS) {
  600. X        $keywords{$k}++ if ($_ =~ /^$k/);
  601. X    }
  602. X}
  603. X
  604. Xforeach $k (@KEYWORDS) {
  605. X    unless ($keywords{$k}) {
  606. X        print "$k? ";
  607. X        $_ = <>;
  608. X        redo if $_ =~ /^\s+$/;
  609. X        push(@msg, "$k: $_");
  610. X        next;
  611. X    }
  612. X}
  613. Xpush (@msg, "Checksum: " . unpack('%32C*', join('', @msg)) . "\n");
  614. X
  615. X&mailx("Vote", $ARGV[1], @msg);
  616. END_OF_FILE
  617. if test 836 -ne `wc -c <'vote'`; then
  618.     echo shar: \"'vote'\" unpacked with wrong size!
  619. fi
  620. chmod +x 'vote'
  621. # end of 'vote'
  622. fi
  623. echo shar: End of archive 1 \(of 1\).
  624. cp /dev/null ark1isdone
  625. MISSING=""
  626. for I in 1 ; do
  627.     if test ! -f ark${I}isdone ; then
  628.     MISSING="${MISSING} ${I}"
  629.     fi
  630. done
  631. if test "${MISSING}" = "" ; then
  632.     echo You have the archive.
  633.     rm -f ark[1-9]isdone
  634. else
  635.     echo You still need to unpack the following archives:
  636.     echo "        " ${MISSING}
  637. fi
  638. ##  End of shell archive.
  639. exit 0
  640.  
  641.  
  642. Volume-Number: Volume 31, Number 74
  643.  
  644.